from pod.std import *
import math
import cairo
from matplotlib.mathtext import MathTextParser
from matplotlib.font_manager import ttfFontProperty

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __repr__(self):
       return "(%f, %f)" % (self.x, self.y)
       
class RGBAColor(object):
   def __init__(self, rgba):
       self.rgba = rgba
       
class Drawable(object):
   def draw(self, ctx): pass

class SubPathCommand(Drawable):
   def __init__(self):
       super(SubPathCommand, self).__init__()

   def draw(self, ctx):
       ctx.new_sub_path()

class ClosePathCommand(Drawable):
   def __init__(self):
       super(ClosePathCommand, self).__init__()

   def draw(self, ctx):
       ctx.close_path()

class Shape(Drawable):
    def __init__(self):
        super(Shape, self).__init__()
        self.points = []
        
class RectangleShape(Shape):
    def __init__(self, x, y, w, h):
        super(RectangleShape, self).__init__()
        self.points.append(Point(x, y))
        self.points.append(Point(w, h))

    def draw(self, ctx):
        ctx.rectangle(self.points[0].x, self.points[0].y, self.points[1].x, self.points[1].y)
        
class CircleShape(Shape):
    def __init__(self, points, radius, reverse=False):
        super(CircleShape, self).__init__()
        #self.points.append(Point(x, y))
        self.points = points
        self.radius = radius
        self.reverse = reverse
        
    def draw(self, ctx):
        if not self.reverse:
            ctx.arc(self.points[0].x, self.points[0].y, self.radius, 0, 2*math.pi)
        else:
            ctx.arc_negative(self.points[0].x, self.points[0].y, self.radius, 0, -2*math.pi)

class LineShape(Shape):
    def __init__(self, points):
        super(LineShape, self).__init__()
        self.points = points
        
    def draw(self, ctx):
        ctx.move_to(self.points[0].x, self.points[0].y)
        ctx.line_to(self.points[1].x, self.points[1].y)
        
class LineToShape(Shape):
    def __init__(self, point):
        super(LineToShape, self).__init__()
        self.point = point
        
    def draw(self, ctx):
        ctx.line_to(self.point.x, self.point.y)
        
class LineCollectionShape(Shape):
    def __init__(self, points):
        super(LineCollectionShape, self).__init__()
        self.points = [point for point in points if isinstance(point, Point)]
        
    def draw(self, ctx):
        start = self.points[0]
        ctx.move_to(start.x, start.y)
        for point in self.points[1:]:
            ctx.line_to(point.x, point.y)            
        
class MathTextShape(Shape):
    parser = MathTextParser("Cairo")
    fontangles = {
        "italic": cairo.FONT_SLANT_ITALIC,
        "normal": cairo.FONT_SLANT_NORMAL, 
        "oblique": cairo.FONT_SLANT_OBLIQUE
    }

    # should get this from the document
    dpi = 70

    fontweights = {
        100          : cairo.FONT_WEIGHT_NORMAL,
        200          : cairo.FONT_WEIGHT_NORMAL,
        300          : cairo.FONT_WEIGHT_NORMAL,
        400          : cairo.FONT_WEIGHT_NORMAL,
        500          : cairo.FONT_WEIGHT_NORMAL,
        600          : cairo.FONT_WEIGHT_BOLD,
        700          : cairo.FONT_WEIGHT_BOLD,
        800          : cairo.FONT_WEIGHT_BOLD,
        900          : cairo.FONT_WEIGHT_BOLD,
        'ultralight' : cairo.FONT_WEIGHT_NORMAL,
        'light'      : cairo.FONT_WEIGHT_NORMAL,
        'normal'     : cairo.FONT_WEIGHT_NORMAL,
        'medium'     : cairo.FONT_WEIGHT_NORMAL,
        'semibold'   : cairo.FONT_WEIGHT_BOLD,
        'bold'       : cairo.FONT_WEIGHT_BOLD,
        'heavy'      : cairo.FONT_WEIGHT_BOLD,
        'ultrabold'  : cairo.FONT_WEIGHT_BOLD,
        'black'      : cairo.FONT_WEIGHT_BOLD        
    }

    def __init__(self, point, text):
        super(MathTextShape, self).__init__()
        self.text = text
        self.points = [point]

    def draw(self, ctx):
        width, height, descent, glyphs, rects = self.parser.parse("$%s$" % self.text)

        ctx.save()
        ctx.translate(self.points[0].x, self.points[0].y)
        for font, fontsize, s, x, y in glyphs:
            ctx.move_to(x, y)            

            ctx.save()
            fontProp = ttfFontProperty(font)
            ctx.select_font_face(fontProp.name, self.fontangles[fontProp.style], self.fontweights[fontProp.weight])
            size = fontsize * self.dpi / 72.0
            ctx.set_font_size(size)
            #ctx.text_path(s.encode("utf-8"))
            ctx.text_path(s)
            ctx.restore()
        #endfor        
        ctx.restore()
        
class TextShape(Shape):
    def __init__(self, point, text, size=12, font="Georgia", slant="normal", bold=False):
        super(TextShape, self).__init__()
        self.text = text
        self.points = [point]
        self.size = size
        self.font = font
        self.slant = cairo.FONT_SLANT_NORMAL
        self.weight = cairo.FONT_WEIGHT_BOLD if bold else cairo.FONT_WEIGHT_NORMAL

    def draw(self, ctx):
        #ctx.set_source_rgb(0.0, 0.0, 0.0)
        ctx.save()
        ctx.select_font_face(self.font, self.slant, self.weight)
        ctx.set_font_size(self.size)
        ctx.move_to(self.points[0].x, self.points[0].y)
        ctx.show_text(self.text)
        ctx.restore()
